package com.zelix.tool;

import com.arthas.client.ArthasTool;

import javax.xml.bind.DatatypeConverter;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;

public class MethodConvert {
    private static final ArrayList IGNORE = new ArrayList<String>() {{
        add("public");
        add("private");
        add("native");
        add("final");
    }};

    public static void main(String[] args) {
        System.out.println(ArthasTool.removeStringLebal("1231313dfdjpdhjdp1@String[123131]"));
        String oo="驃岂Ⲅ✾籮⫑ꦞ暐》縖莜㈜褦작폵␚뒢憥흌汱㜾";
        char[] chars=oo.toCharArray();
        chars[9]= (char) (chars[9]^253);
        System.out.println(DatatypeConverter.printHexBinary(String.valueOf(chars).getBytes(StandardCharsets.UTF_8)));
        System.out.println(Base64.getEncoder().encodeToString(String.valueOf(chars).getBytes(StandardCharsets.UTF_8)));
        System.out.println(DatatypeConverter.parseHexBinary("E9A983E5B282E2B284E29CBEE7B1AEE2AB91EAA69EE69A90E3808BE7B896E88E9CE3889CE8A4A6EC9E91ED8FB5E2909AEB92A2E686A5ED9D8CE6B1B1E39CBE"));
        String src = "public static java.lang.StringBuilder java.lang.StringBuilder.append(java.lang.String)";
        analyMethod(src);
        src = "public static java.lang.invoke.MethodHandle java.lang.invoke.MethodHandles.explicitCastArguments(java.lang.invoke.MethodHandle,java.lang.invoke.MethodType)";
        analyMethod(src);
        src = "public static java.lang.invoke.MethodHandle java.lang.invoke.MethodHandles.insertArguments(java.lang.invoke.MethodHandle,int,java.lang.Object[])";
        analyMethod(src);
        src = "public byte[] java.lang.String.getBytes(java.nio.charset.Charset)";
        analyMethod(src);
        src = "public static java.lang.String[] fuck_the_regulations_v320.eM.b()";
        analyMethod(src);

        Method[] methods = Runnable.class.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
    }

    /**
     * 分析java.lang.reflect.Method.toString()输出的结果
     *
     * @param src
     */
    public static void analyMethod(String src) {
        //函数括号后throws丢弃
        src = src.substring(0, src.indexOf(')') + 1);

        //空格分割
        String[] srcs = src.split(" ");

        //必须要有返回值 方法名(方法描述)
        if (srcs.length < 2) {
            return;
        }
        //方法调用者 方法名 参数
        List<String> args = analyOwnerNameArgs(srcs[srcs.length - 1]);
        //方法返回
        String rtn = analyType(srcs[srcs.length - 2]);

        System.out.println(args.get(0) + "." + args.get(1) + args.get(2) + rtn);

        //分析了后面两个了,减去2
        for (int i = 0; i < srcs.length - 2; i++) {
            if (IGNORE.contains(srcs[i])) {
                continue;
            } else {
                //没有interface方法,interface接口的方法都是abstract的
                if (srcs[i].equals("static")) {

                } else if (srcs[i].equals("abstract")) {

                } else {
                    System.out.println("未知修饰符:" + srcs[i]);
                }
            }
        }
    }

    /**
     * 解析类型,方法的参数和返回值可用
     *
     * @param str
     * @return
     */
    private static String analyType(String str) {

        //比方法无参数
        if (str.length() == 0) {
            return "";
        }

        StringBuilder builder = new StringBuilder();

        //处理数组
        if (str.endsWith("[]")) {
            builder.append("[");
            str = str.substring(0, str.length() - 2);
        }

        if (str.contains(".")) {//类
            builder.append("L" + analyMember(str) + ";");
        } else {
            builder.append(analyMember(str));
        }

        return builder.toString();
    }

    /**
     * 分析成员
     *
     * @param str
     * @return
     */
    private static String analyMember(String str) {
        if (str.contains(".")) {//类
            return str.replaceAll("\\.", "/");
        }

        return innerType(str);
    }

    /**
     * 内部基础类型转换
     *
     * @param str
     * @return
     */
    private static String innerType(String str) {
        switch (str) {
            case "int":
                return "I";
            case "long":
                return "J";
            case "byte":
                return "B";
            case "void":
                return "V";
            case "boolean":
                return "Z";
            case "char":
                return "C";
            case "double":
                return "D";
            case "float":
                return "F";
            case "short":
                return "S";
            default:
                System.out.println("------------------innerType------------------" + str + "***");
                return str;
        }
    }

    private static List<String> analyOwnerNameArgs(String ownerNameArgs) {
        List<String> rtn = new ArrayList();
        //取参数
        int argStart = ownerNameArgs.indexOf('(') + 1;
        int argEnd = ownerNameArgs.indexOf(')');
        //参数数组
        String[] args = ownerNameArgs.substring(argStart, argEnd).split(",");
        StringBuilder argsb = new StringBuilder();
        for (String arg : args) {
            argsb.append(analyType(arg));
        }
        //取方法名
        String ownerName = ownerNameArgs.substring(0, argStart - 1);
        if (ownerName.contains(".")) {//是类
            //方法名
            String name = ownerName.substring(ownerName.lastIndexOf('.') + 1);
            //方法所有者
            String owner = ownerName.substring(0, ownerName.lastIndexOf('.'));
            rtn.add(analyMember(owner));
            rtn.add(name);
            rtn.add("(" + argsb + ")");
            return rtn;
        } else {
            System.out.println("------------------analyOwnerNameArgs------------------" + ownerNameArgs);
            return rtn;
        }
    }
}
